package org.lgh.webchatback.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.netty.channel.Channel;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import org.lgh.webchatback.bo.UserBo;
import org.lgh.webchatback.common.R;
import org.lgh.webchatback.entity.ChatMessage;
import org.lgh.webchatback.entity.FriendsRequest;
import org.lgh.webchatback.entity.MyFriends;
import org.lgh.webchatback.entity.Users;
import org.lgh.webchatback.enums.MsgActionEnum;
import org.lgh.webchatback.enums.MsgSignFlagEnum;
import org.lgh.webchatback.enums.SearchFriendsStatusEnum;
import org.lgh.webchatback.mapper.UsersMapper;
import org.lgh.webchatback.netty.ChatMsg;
import org.lgh.webchatback.netty.DataContent;
import org.lgh.webchatback.netty.UserChannelRel;
import org.lgh.webchatback.service.ChatMessageService;
import org.lgh.webchatback.service.FriendsRequestService;
import org.lgh.webchatback.service.MyFriendsService;
import org.lgh.webchatback.service.UserService;
import org.lgh.webchatback.utils.FastDFSClient;
import org.lgh.webchatback.utils.FileUtils;
import org.lgh.webchatback.utils.JsonUtils;
import org.lgh.webchatback.utils.QRCodeUtils;
import org.lgh.webchatback.vo.FriendsRequestVO;
import org.lgh.webchatback.vo.MyFriendsVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author wei-xhh
 * @date 2022-01-19
 */
@Service
public class UserServiceImpl extends ServiceImpl<UsersMapper, Users> implements UserService {

    @Autowired
    FastDFSClient fastDFSClient;

    @Autowired
    QRCodeUtils qrCodeUtils;

    @Autowired
    MyFriendsService myFriendsService;

    @Autowired
    FriendsRequestService friendsRequestService;

    @Autowired
    ChatMessageService chatMessageService;

    @Override
    public R registerOrLogin(String username, String password, String cid) {
        // 注册或登录
        Users user = this.getOne(new QueryWrapper<Users>().eq("username", username));
        if (user != null) {
            // 用户存在,登录
            String pwd = user.getPassword();
            if (pwd.equals(password)) {
                return R.data(user);
            }
        } else {
            // 注册
            Users users = new Users();
            users.setUsername(username);
            users.setNickname(username);
            users.setCid(cid);
            users.setPassword(password);
            // 生成二维码
            String qrCodePath = "D://user" + cid + "qrcode.png";
            qrCodeUtils.createQRCode(qrCodePath, "bird_qrcode:" + username);
            MultipartFile qrcodeFile = FileUtils.fileToMultipart(qrCodePath);
            String qrcodeURL = "";
            try {
                qrcodeURL = fastDFSClient.uploadQRCode(qrcodeFile);
            } catch (IOException e) {
                e.printStackTrace();
            }
            users.setQrcode(qrcodeURL);
            boolean save = this.save(users);
            if (save) {
                return R.data(users);
            }
        }
        return R.error();
    }

    @Override
    public R setNickname(String id, String nickname) {
        Users users = this.getById(id);
        if (users != null) {
            users.setNickname(nickname);
            boolean b = this.updateById(users);
            if (b) {
                return R.data(users);
            }
        }
        return R.error();
    }

    @Override
    public R uploadFaceBase64(UserBo userBo) throws Exception {
        String base64Data = userBo.getFaceData();
        String userFacePath = "D:/" + userBo.getUserId() + "userFaceBase64.png";
        // 调用FileUtils 类中的方法将Base64转为文件对象
        FileUtils.base64ToFile(userFacePath, base64Data);
        MultipartFile multipartFile = FileUtils.fileToMultipart(userFacePath);
        // 获取fastDFS上传图片的路径
        String url = fastDFSClient.uploadBase64(multipartFile);
        System.out.println("666666666666:" + url);
        String thump = "_150_150.";
        String[] arr = url.split("\\.");
        String thumpImgUrl = arr[0] + thump + arr[1];
        // 更新用户头像
        String userId = userBo.getUserId();
        Users users = this.getById(userId);
        if (users != null) {
            users.setFaceImage(thumpImgUrl);
            users.setFaceImageBig(url);
            boolean b = this.updateById(users);
            if (b) {
                return R.data(users);
            }
        }
        return R.error();
    }

    @Override
    public R searchFriend(String myUserId, String friendUserName) {
        // 1.有这个人
        Users users = this.getOne(new QueryWrapper<Users>().eq("username", friendUserName));
        if (users != null) {
            Integer id = users.getId();
            // 2. 添加自己
            if (Integer.parseInt(myUserId) == id) {
                return R.datae(SearchFriendsStatusEnum.NOT_YOURSELF.msg);
            } else {
                QueryWrapper<MyFriends> queryWrapper = new QueryWrapper<>();
                QueryWrapper<MyFriends> eq =
                        queryWrapper.eq("my_user_id", myUserId).eq("my_friend_user_id", id);
                MyFriends serviceOne = myFriendsService.getOne(eq);
                if (serviceOne != null) {
                    return R.datae(SearchFriendsStatusEnum.ALREADY_FRIENDS.msg);
                }
                return R.data(users);
            }
        }
        return R.datae(SearchFriendsStatusEnum.USER_NOT_EXIST.msg);
    }

    @Override
    public R addFriendRequest(String myUserId, String friendUserName) {
        // 1.有这个人
        Users users = this.getOne(new QueryWrapper<Users>().eq("username", friendUserName));
        if (users != null) {
            Integer id = users.getId();
            // 2. 添加自己
            if (Integer.parseInt(myUserId) == id) {
                return R.datae(SearchFriendsStatusEnum.NOT_YOURSELF.msg);
            } else {
                QueryWrapper<MyFriends> queryWrapper = new QueryWrapper<>();
                QueryWrapper<MyFriends> eq =
                        queryWrapper.eq("my_user_id", myUserId).eq("my_friend_user_id", id);
                MyFriends serviceOne = myFriendsService.getOne(eq);
                if (serviceOne != null) {
                    return R.datae(SearchFriendsStatusEnum.ALREADY_FRIENDS.msg);
                }
                // 保存到好友请求表中
                FriendsRequest friendsRequest = new FriendsRequest();
                friendsRequest.setAcceptUserId(id);
                friendsRequest.setSendUserId(Integer.parseInt(myUserId));
                friendsRequest.setRequestDateTime(new Date());
                boolean save = friendsRequestService.save(friendsRequest);
                return save ? R.success() : R.error();
            }
        }
        return R.datae(SearchFriendsStatusEnum.USER_NOT_EXIST.msg);
    }

    @Override
    public R queryFriendRequest(String userId) {
        QueryWrapper<FriendsRequest> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("accept_user_id", Integer.parseInt(userId));
        List<FriendsRequest> list = friendsRequestService.list(queryWrapper);
        List<FriendsRequestVO> collect = list.stream().map(item -> {
            FriendsRequestVO requestVO = new FriendsRequestVO();
            requestVO.setSendUserId(item.getSendUserId());
            Users users = this.getById(item.getSendUserId());
            requestVO.setSendFaceImage(users.getFaceImage());
            requestVO.setSendNickname(users.getNickname());
            requestVO.setSendUsername(users.getUsername());
            return requestVO;
        }).collect(Collectors.toList());
        return R.data(collect);
    }

    @Override
    public R operFriendRequest(String acceptUserId, String sendUserId, String operType) {
        // operType为0忽略，1通过
        QueryWrapper<FriendsRequest> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("accept_user_id", acceptUserId).eq("send_user_id", sendUserId);

        if ("0".equals(operType)) {
            boolean remove = friendsRequestService.remove(queryWrapper);
            if (!remove) {
                return R.error();
            }
        } else if ("1".equals(operType)) {
            boolean remove = friendsRequestService.remove(queryWrapper);
            if (!remove) {
                return R.error();
            }
            MyFriends myFriend1 = new MyFriends();
            myFriend1.setMyUserId(Integer.parseInt(acceptUserId));
            myFriend1.setMyFriendUserId(Integer.parseInt(sendUserId));
            boolean save = myFriendsService.save(myFriend1);
            MyFriends myFriend2 = new MyFriends();
            myFriend2.setMyUserId(Integer.parseInt(sendUserId));
            myFriend2.setMyFriendUserId(Integer.parseInt(acceptUserId));
            boolean myFriendSave = myFriendsService.save(myFriend2);
            if (!save || !myFriendSave) {
                return R.error();
            }

            Channel sendChannel = UserChannelRel.get(sendUserId);
            if(sendChannel != null) {
                // 使用websocket主动推送消息到请求发起者，更新他的通讯录为最新
                DataContent dataContent = new DataContent();
                dataContent.setAction(MsgActionEnum.PULL_FRIEND.type);

                // 消息的推送
                sendChannel.writeAndFlush(new TextWebSocketFrame(JsonUtils.objectToJson(dataContent)));
            }

        }
        QueryWrapper<MyFriends> myFriendsQueryWrapper = new QueryWrapper<>();
        queryWrapper.eq("accept_user_id", acceptUserId).eq("send_user_id", sendUserId);

        List<MyFriends> list = myFriendsService.list(myFriendsQueryWrapper);
        List<MyFriendsVO> collect = list.stream().map(item -> {
            MyFriendsVO myFriendsVO = new MyFriendsVO();
            myFriendsVO.setFriendUserId(Integer.parseInt(sendUserId));
            Users byId = this.getById(sendUserId);
            myFriendsVO.setFriendFaceImage(byId.getFaceImage());
            myFriendsVO.setFriendNickname(byId.getNickname());
            myFriendsVO.setFriendUsername(byId.getUsername());
            return myFriendsVO;
        }).collect(Collectors.toList());


        return R.data(collect);
    }

    @Override
    public R myFriends(String userId) {
        QueryWrapper<MyFriends> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("my_user_id", userId);
        List<MyFriends> list = myFriendsService.list(queryWrapper);
        List<MyFriendsVO> collect = list.stream().map(item -> {
            MyFriendsVO myFriendsVO = new MyFriendsVO();
            myFriendsVO.setFriendUserId(item.getMyFriendUserId());
            Users byId = this.getById(item.getMyFriendUserId());
            myFriendsVO.setFriendUsername(byId.getUsername());
            myFriendsVO.setFriendNickname(byId.getNickname());
            myFriendsVO.setFriendFaceImage(byId.getFaceImage());
            return myFriendsVO;
        }).collect(Collectors.toList());
        return R.data(collect);
    }

    @Override
    public String saveMsg(ChatMsg chatMsg) {
        ChatMessage chatMessage = new ChatMessage();
        String msgId = UUID.randomUUID().toString().replace("-", "");
        chatMessage.setId(msgId);
        chatMessage.setAcceptUserId(chatMsg.getReceiverId());
        chatMessage.setSendUserId(chatMsg.getSenderId());
        chatMessage.setCreateTime(new Date());
        chatMessage.setSignFlag(MsgSignFlagEnum.unsign.type);
        chatMessage.setMsg(chatMsg.getMsg());
        chatMessageService.save(chatMessage);
        return msgId;
    }

    @Override
    public void updateMsgSigned(List<String> msgIdList) {
        for (String s : msgIdList) {
            ChatMessage chatMessage = new ChatMessage();
            chatMessage.setId(s);
            chatMessage.setSignFlag(1);
            chatMessageService.updateById(chatMessage);
        }
    }

    @Override
    public R getUnReadMsgList(String acceptUserId) {
        List<ChatMessage> sign_flag = chatMessageService.list(
                new QueryWrapper<ChatMessage>().eq("sign_flag", 0).eq("accept_user_id", acceptUserId));
        return R.data(sign_flag);
    }
}
